package com.warmheart.base.config;

import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.apache.ibatis.executor.resultset.DefaultResultSetHandler;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ResultMap;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;

import com.warmheart.base.entity.BaseEntity;

/**
 * 
 * @ClassName: RsInterceptor
 * @Description: 处理扩展属性
 * @author ZhangJianyang
 * @date 2025-06-16 09:37:02
 *
 */
@Intercepts({ @Signature(type = ResultSetHandler.class, method = "handleResultSets", args = { Statement.class }) })
public class RsInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Exception {
        List<Map<String, Object>> rsList = new ArrayList<Map<String, Object>>();
        DefaultResultSetHandler defaultResultSetHandler = (DefaultResultSetHandler) invocation.getTarget();
        MetaObject metaStatementHandler = SystemMetaObject.forObject(defaultResultSetHandler);
        MappedStatement mappedStatement = (MappedStatement) metaStatementHandler.getValue("mappedStatement");
        // 获取节点属性的集合
        List<ResultMap> resultMaps = mappedStatement.getResultMaps();
        // 获取返回的实体类类型名
        int resultMapCount = resultMaps.size();
        if (resultMapCount > 0) {
            Class<?> resultType = resultMaps.get(0).getType();
            if (BaseEntity.class.isAssignableFrom(resultType)) {
                Statement statement = (Statement) invocation.getArgs()[0];
                ResultSet resultSet = statement.getResultSet();
                if (resultSet != null) {
                    // 获得对应列名
                    ResultSetMetaData rsmd = resultSet.getMetaData();
                    List<String> columnList = new ArrayList<String>();
                    for (int i = 1; i <= rsmd.getColumnCount(); i++) {
                        columnList.add(rsmd.getColumnLabel(i));
                    }
                    Set<String> fieldNameSet = new HashSet<String>();
                    while (resultType != Object.class) {
                        Field[] fieldArr = resultType.getDeclaredFields();
                        if (fieldArr != null && fieldArr.length > 0) {
                            for (Field currField : fieldArr) {
                                fieldNameSet.add(currField.getName());
                            }
                        }
                        resultType = resultType.getSuperclass();
                    }
                    Set<String> extraSet = new HashSet<String>();
                    if (columnList.size() > 0) {
                        for (String rsColumnName : columnList) {
                            if (!fieldNameSet.contains(rsColumnName)) {
                                extraSet.add(rsColumnName);
                            }
                        }
                    }
                    if (extraSet.size() > 0) {
                        boolean readFlag = false;
                        while (resultSet.next()) {
                            Map<String, Object> rsMap = new HashMap<String, Object>();
                            for (String extraColName : extraSet) {
                                rsMap.put(extraColName, resultSet.getObject(extraColName));
                            }
                            rsList.add(rsMap);
                            readFlag = true;
                        }
                        if (readFlag) {
                            // 重新移动游标至第一行之前
                            resultSet.beforeFirst();
                        }
                    }
                }
            }
        }
        Object resultObj = invocation.proceed();
        if (rsList.size() > 0) {
            int i = 0;
            if (resultObj != null && resultObj instanceof List<?>) {
                List<?> resultList = (List<?>) resultObj;
                if (resultList != null && resultList.size() == rsList.size()) {
                    for (Object currObj : resultList) {
                        if (currObj instanceof BaseEntity) {
                            BaseEntity<?, ?> currBaseEntity = (BaseEntity<?, ?>) currObj;
                            currBaseEntity.getRsMap().putAll(rsList.get(i));
                            i++;
                        }
                    }
                }
            }
        }
        return resultObj;
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
    }
}
